package com.bss.service;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.faces.model.DataModel;
import javax.faces.model.ListDataModel;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.andy.basics.Constants;
import com.andy.basics.Dao;
import com.bss.dao.AdmissionDao;
import com.bss.dao.AttendentDao;
import com.bss.dao.CurrentAttendentDao;
import com.bss.dao.PassportDao;
import com.bss.model.Admission;
import com.bss.model.Attendent;
import com.bss.model.CurrentAttendent;
import com.bss.model.Patient;

@Service
@Scope("session")
public class CurrentAttendentService extends com.andy.basics.Service<CurrentAttendent> {

	private static final String CLASS = CurrentAttendentService.class.getName();

	private static final Logger DEBUG = Logger.getLogger(Constants.DEBUG_KEY + CurrentAttendentService.CLASS);

	private static final Logger AUDIT = Logger.getLogger(Constants.AUDIT_KEY + CurrentAttendentService.CLASS);

	private static final Logger ERROR = Logger.getLogger(Constants.ERROR_KEY + CurrentAttendentService.CLASS);

	@Autowired
	private AdmissionDao admissionDao;

	@Autowired
	private PassportDao passportDao;

	private Admission admission;

	public Admission getAdmission() {
		if (this.admission == null) {
			this.admission = new Admission();
		}
		return this.admission;
	}

	public void setAdmission(final Admission admission) {
		this.admission = admission;
	}

	private List<CurrentAttendent> currentAttendents;

	public List<CurrentAttendent> getCurrentAttendents() {
		return this.currentAttendents;
	}

	public void setCurrentAttendents(final List<CurrentAttendent> currentAttendents) {
		this.currentAttendents = currentAttendents;
	}

	private DataModel selectableCurrentAttendent;

	@Autowired
	private CurrentAttendentDao currentAttendentDao;

	@Autowired
	private AttendentDao attendentDao;

	private List<Attendent> allAttendents;

	private DataModel allAttendentsDataModel;

	@Override
	public DataModel getDataModel() {
		return this.dataModel;
	}

	@Override
	public Dao<CurrentAttendent> getDao() {
		return this.currentAttendentDao;
	}

	public DataModel getSelectableCurrentAttendent() {
		return this.selectableCurrentAttendent;
	}

	public DataModel getAttendentsData(final Patient patient, final String attendentName) {
		this.selectableCurrentAttendent = new ListDataModel(this.attendentDao.findAllForPatient(patient, "name like '"
				+ attendentName + "%'"));
		return this.selectableCurrentAttendent;
	}

	@Transactional
	public String selectAdmission(final Admission admission) {
		this.admission = this.admissionDao.findById(admission.getId());
		this.reload();
		return null;
	}

	public List<Attendent> findAllAttendents(final Patient patient) {
		return this.attendentDao.findAllForPatient(patient, "name is not null");
	}

	@Override
	@Transactional
	public void save(CurrentAttendent ca) {

		if (ca.getAttendent().getId() == 0) {
			if ("Passport".equalsIgnoreCase(ca.getAttendent().getIdCardType().getName())) {
				if (ca.getAttendent().getPassport().getId() == 0) {
					this.passportDao.persist(ca.getAttendent().getPassport());
				} else {
					this.passportDao.update(ca.getAttendent().getPassport());
				}
			} else {
				ca.getAttendent().setPassport(null);
			}
			this.attendentDao.persist(ca.getAttendent());
		} else {
			if ("Passport".equalsIgnoreCase(ca.getAttendent().getIdCardType().getName())) {
				if (ca.getAttendent().getPassport().getId() == 0) {
					this.passportDao.persist(ca.getAttendent().getPassport());
				} else {
					this.passportDao.update(ca.getAttendent().getPassport());
				}
			} else {
				ca.getAttendent().setPassport(null);
			}
			this.attendentDao.update(ca.getAttendent());
		}
		this.currentAttendentDao.persist(ca);

		this.reload();
	}

	@Override
	public void update(CurrentAttendent ca) {

		if ("Passport".equalsIgnoreCase(ca.getAttendent().getIdCardType().getName())) {
			if (ca.getAttendent().getPassport().getId() == 0) {
				this.passportDao.persist(ca.getAttendent().getPassport());
			} else {
				this.passportDao.update(ca.getAttendent().getPassport());
			}
		} else {
			ca.getAttendent().setPassport(null);
		}
		this.attendentDao.update(ca.getAttendent());

		super.update(ca);

		this.reload();
	}

	@Transactional
	public void exitAttendent(Date date) {

		CurrentAttendentService.DEBUG.debug("Selected CurrentAttendent rowIndex: " + this.dataModel.getRowIndex());
		CurrentAttendent currentAttendent = this.getModels().get(this.dataModel.getRowIndex());
		currentAttendent = this.currentAttendentDao.findById(currentAttendent.getId());
		currentAttendent.setDateOfLeave(date);

		this.currentAttendentDao.update(currentAttendent);

		this.reloadCurrent(this.admission);
	}

	public void setAllAttendentsDataModel(DataModel allAttendentsDataModel) {
		this.allAttendentsDataModel = allAttendentsDataModel;
	}

	public DataModel getAllAttendentsDataModel() {
		return this.allAttendentsDataModel;
	}

	public String checkin(Date date) {
		Attendent attendent = this.allAttendents.get(this.allAttendentsDataModel.getRowIndex());

		List<CurrentAttendent> currentAttendents = this.currentAttendentDao.find("admission.id = " + this.getAdmission().getId()
				+ " and attendent.id = " + attendent.getId() + " and dateOfArrival is not null and dateOfLeave is null");
		if ((currentAttendents != null) && (currentAttendents.size() > 0)) {
			return "Attendent " + attendent.getName()
					+ " is already present with the patient currently ! Try adding another attendent or a new one";
		}

		attendent = this.attendentDao.findById(attendent.getId());

		CurrentAttendent currentAttendent = new CurrentAttendent();
		currentAttendent.setAttendent(attendent);
		currentAttendent.setAdmission(this.getAdmission());
		currentAttendent.setDateOfArrival(date);
		currentAttendent.setDateOfLeave(null);

		this.currentAttendentDao.persist(currentAttendent);

		this.reloadCurrent(this.admission);

		return Constants.SUCCESS;
	}

	public void reset() {
		this.allAttendentsDataModel = null;
		this.dataModel = null;
	}

	@Override
	public void reload() {
		if (this.getAdmission().getId() == 0) {
			this.models = new ArrayList<CurrentAttendent>();
			this.dataModel = new ListDataModel(this.models);
			this.allAttendents = new ArrayList<Attendent>();
			this.allAttendentsDataModel = new ListDataModel(this.allAttendents);
		} else {
			this.admission = this.admissionDao.findById(this.getAdmission().getId());

			this.reloadCurrent(this.admission);
			this.reloadAll(this.admission);

			CurrentAttendentService.DEBUG.debug("Now current attendents size is " + this.models.size() + ", "
					+ this.dataModel.getRowCount());

		}
	}

	public void reloadAll(Admission admission) {
		this.allAttendents = this.attendentDao.find("patient.id = " + this.admission.getPatient().getId());
		this.allAttendentsDataModel = new ListDataModel(this.allAttendents);
	}

	public void reloadCurrent(Admission admission) {
		this.models = this.currentAttendentDao.find("admission.id = " + this.admission.getId()
				+ " and dateOfArrival is not null and dateOfLeave is null");
		this.dataModel = new ListDataModel(this.models);
	}

}
